-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[MNG-8696] PathModularizationCache needs to set cache #2219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…o a public constructor in DefaultDependencyResolverResult
Alternatively, we can make the constructor package-private and add another constructor without the A few months ago, a started a branch where I tried to reduce the visibility of some Maven internal classes. It required moving some classes to a common package (in this case, we would need to move |
Yes, if we can move more classes into the same packages we can reduce visibility of a lot of things. Excessive proliferation of subpackages is a major antipattern in Java that leads to excessive visibility. It's probably second only to IDEs that mark classes and methods public by default. |
The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PTAL. Took @desruisseaux 's suggestion to make the constructor package-private and add another constructor without the PathModularizationCache argument, which delegates to the package-private constructor with a null argument.
DependencyResolverRequest request, | ||
PathModularizationCache cache, | ||
List<Exception> exceptions, | ||
Node root, | ||
int count) { | ||
this.request = request; | ||
this.cache = cache; | ||
if (cache == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This if
… else
block could be replaced by this.cache = Objects.requireNonNull(cache)
. For consistency, we may do the same for other arguments too except root
which is nullable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that's the same. cache is nullable. We need to create a cache if the argument is null, not throw an exception. Null is passed for this argument and we don't want to break those existing usages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new constructor should replace all the calls to the previous constructor with a null cache. We are sure that the new constructor is invoked outside the package since the old constructor became package-private. So we only need to ensure that the calls inside the package pass a non-null cache, and I think that it is already the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's risky and brittle to allow null caches given the multiple locations that invoke methods on the cache and the lack of test coverage on this class. It is unsafe to allow this field to be null, even if the constructor argument is. Even if it doesn't cause an uncaught NPE now it will in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I agree, which is why my proposal above was to use Objects.requireNonNull
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I don't want to throw a NullPointerException. We can easily create a cache here..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rational was that a cache created here is of limited use. The intend was to have a session-wide cache, which is why this method was requesting the cache in argument. The creation of a cache in the constructor was only a temporary workaround for the fact that we have not investigated where a session-wide cache should be stored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whatever the intent was, this field is dereferenced without null checks in multiple places. That's dangerous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree that it is dereferenced without null checks, which is why the proposal above was to use Objects.requireNonNull
in the constructor. Then, since the constructor become package-private as a result of the change in this pull request, we can easily verify that all invocations of this constructor pass a non-null cache. But anyway, this is not very important. We can leave it as is for now and revisit after we determined where the cache should be stored.
DependencyResolverRequest request, | ||
PathModularizationCache cache, | ||
List<Exception> exceptions, | ||
Node root, | ||
int count) { | ||
this.request = request; | ||
this.cache = cache; | ||
if (cache == null) { | ||
this.cache = new PathModularizationCache(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could init on declaration to give context for default trading coupling for cohesion. This case is then implied default making use for only dedicated second if.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might consider init on declaration to give cohesion; default - making first things first.
DependencyResolverRequest request, | ||
PathModularizationCache cache, | ||
List<Exception> exceptions, | ||
Node root, | ||
int count) { | ||
this.request = request; | ||
this.cache = cache; | ||
if (cache == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (cache == null) { | |
if (cache != null) { |
take happy path.
@@ -102,19 +102,27 @@ public class DefaultDependencyResolverResult implements DependencyResolverResult | |||
* to {@link #addDependency(Node, Dependency, Predicate, Path)}. | |||
* | |||
* @param request the corresponding request | |||
* @param cache cache of module information about each dependency |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private final PathModularizationCache cache = new PathModularizationCache();
L:98
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the particular case of this issue, creating the cache at the location where the field is defined is the opposite of the intend, because it makes the PathModularizationCache
lifetime strongly coupled with the DefaultDependencyResolverResult
lifetime. Such coupling makes PathModularizationCache
close to useless. It was done that way in the previous version of this class only as a workaround for the fact that I didn't knew where to store a session-wide cache, but that workaround was intended to be temporary.
More details in a next comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my suggest would not compile. im sorry.
I think that the
The pull #2347 tries to address the same issue as this pull request, but in a way that makes more apparent that |
…o a public constructor in DefaultDependencyResolverResult. It only hasn't failed yet because we're only passing null for this argument but there's a TODO to change that.
Alternatively, we could remove PathModularizationCache from the DefaultDependencyResolverResult.